﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using lite;
using System.Data.SqlClient;
using Csla.Data;
using Csla;
using OpenExpressApp;
using System.Collections;
using Csla.Core;
using OpenExpressApp.ORM;
using OpenExpressApp.MetaAttribute;
using OpenExpressApp.MetaModel;
using OpenExpressApp.Types;
using OpenExpressApp.DB.Utils;

namespace OpenExpressApp.Module.Library
{
    [Serializable]
    public partial class OrgList : GBusinessOrderedTreeListBase<OrgList, Org>
    {
        #region  Factory Methods

        public static OrgList GetList()
        {
            return DataPortal.Fetch<OrgList>();
        }


        private OrgList()
        {
            /* require use of factory methods */
            AllowNew = true;
            /* 不允许修改时，AutoUI绑定列表控件时会使得控件只读  */
            //AllowEdit = false;            
        }

        protected override object AddNewCore()
        {
            var item = Org.New();
            Add(item);
            return item;
        }

        #endregion

        #region  Data Access

        private void DataPortal_Fetch()
        {
            RaiseListChangedEvents = false;
            using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
            {
                IQuery q = db.Query();
                var list = db.Select<Org>(q);
                foreach (var item in list)
                {
                    this.Add(Org.GetLazy(item.Id));
                }
            }
            RaiseListChangedEvents = true;
        }

        #endregion
    }

    [Serializable]
    [Table]
    [DefaultObject("7F757E57-99B8-44F9-BF2D-DAECE8111242", Catalog = "用户权限", Index = 1), Label("部门管理")]
    public partial class Org : GBusinessBase<Org>, ITreeNode, IOrderedObject
    {
        #region  Business Methods

        private static PropertyInfo<Guid> IdProperty =
            RegisterProperty(new PropertyInfo<Guid>("Id"));
        [System.ComponentModel.DataObjectField(true, true)]
        [Column, PK]
        [EntityProperty]
        [Indexable(IndexModeEnum.IndexModeAlways)]
        public Guid Id
        {
            get { return GetProperty(IdProperty); }
            set { SetProperty(IdProperty, value); }
        }

        private static PropertyInfo<Guid?> PidProperty =
    RegisterProperty(new PropertyInfo<Guid?>("Pid"));
        [System.ComponentModel.DataObjectField(true, true)]
        [Column]
        [EntityProperty]
        public Guid? Pid
        {
            get { return GetProperty(PidProperty); }
            set { SetProperty(PidProperty, value); }
        }

        private static PropertyInfo<string> CodeProperty =
  RegisterProperty(new PropertyInfo<string>("Code"));
        [Column]
        [EntityProperty]
        [Required, ShowInList, ShowInDetail, Label("编码"), ShowInLookup]
        public string Code
        {
            get { return GetProperty(CodeProperty); }
            set { SetProperty(CodeProperty, value); }
        }

        private static PropertyInfo<string> NameProperty =
          RegisterProperty(new PropertyInfo<string>("Name"));
        [Column]
        [EntityProperty]
        [Required, IsTitle, ShowInList, ShowInDetail, Label("名称")]
        public string Name
        {
            get { return GetProperty(NameProperty); }
            set { SetProperty(NameProperty, value); }
        }

        private static PropertyInfo<int> OrderNoProperty =
     RegisterProperty(new PropertyInfo<int>("OrderNo"));
        [Column]
        [EntityProperty]
        [Required, Label("顺序号")]
        public int OrderNo
        {
            get { return GetProperty(OrderNoProperty); }
            set { SetProperty(OrderNoProperty, value); }
        }

        private static PropertyInfo<OrgPositions> OrgPositionsProperty =
          RegisterProperty(new PropertyInfo<OrgPositions>("OrgPositions"));
        [Association]
        public OrgPositions OrgPositions
        {
            get
            {
                if (!FieldManager.FieldExists(OrgPositionsProperty))
                {
                    LoadProperty(OrgPositionsProperty, OrgPositions.NewChild());
                }
                return GetProperty(OrgPositionsProperty);
            }
        }

        public override BusinessBase MergeOldObject(BusinessBase oldObject)
        {
            if (null == oldObject) return null;

            Org _detailItem = oldObject as Org;

            LoadProperty(IdProperty, _detailItem.Id);
            LoadProperty(PidProperty, _detailItem.Pid);
            LoadProperty(CodeProperty, _detailItem.Code);
            LoadProperty(NameProperty, _detailItem.Name);
            LoadProperty(OrderNoProperty, _detailItem.OrderNo);


            var orgPositions = OrgPositions.NewChild();
            orgPositions.AddRange((oldObject as Org).OrgPositions);
            LoadProperty(OrgPositionsProperty, orgPositions);

            return base.MergeOldObject(oldObject);
        }

        #endregion

        #region  Validation Rules

        protected override void AddBusinessRules()
        {
            // ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, new Csla.Validation.RuleArgs(NameProperty));
        }

        #endregion

        #region  Factory Methods

        private Org()
        {
            IsObjectLazy = true;
        }

        public static Org New()
        {
            return DataPortal.Create<Org>();
        }

        public static Org Get(Guid id)
        {
            return DataPortal.Fetch<Org>(new SingleLazyCriteria<Org, Guid>(id, false));
        }

        public static Org GetLazy(Guid id)
        {
            return DataPortal.Fetch<Org>(new SingleLazyCriteria<Org, Guid>(id, true));
        }

        public static void Delete(Guid id)
        {
            DataPortal.Delete(new SingleCriteria<Org, Guid>(id));
        }

        #endregion

        #region  Data Access

        [RunLocal]
        protected override void DataPortal_Create()
        {
            LoadProperty(IdProperty, Guid.NewGuid());
            this.ValidationRules.CheckRules();
        }

        private void DataPortal_Fetch(SingleLazyCriteria<Org, Guid> criteria)
        {
            using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
            {
                IQuery q = db.Query();
                q.Constrain("Id").Equal(criteria.Value);
                var data = db.Select<Org>(q)[0];
                LoadProperty(IdProperty, data.Id);
                LoadProperty(PidProperty, data.Pid);
                LoadProperty(CodeProperty, data.Code);
                LoadProperty(NameProperty, data.Name);
                LoadProperty(OrderNoProperty, data.OrderNo);

                this.IsObjectLazy = criteria.IsObjectLazy;
                if (!IsObjectLazy)
                {
                    LoadProperty(OrgPositionsProperty, OrgPositions.GetChild(this));
                }
            }
        }

        private void CheckUniqueCode(IDb db)
        {
            string sql = string.Format("select 1 from [Org] where Code = '{0}' and Id != '{1}'", this.Code, this.Id);
            if (db.ExecSql(sql).Rows > 0)
            {
                throw new Exception("已经有这个编码的组织了。");
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_Insert()
        {
            using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
            {
                this.CheckUniqueCode(db);

                db.Insert(this);
                // update child objects
                FieldManager.UpdateChildren(this);
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_Update()
        {
            using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
            {
                this.CheckUniqueCode(db);

                db.Update(this);
                // update child objects
                FieldManager.UpdateChildren(this);
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_DeleteSelf()
        {
            DataPortal_Delete(this.Id);
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        private void DataPortal_Delete(Guid id)
        {
            using (var db = DBHelper.CreateDb(ConnectionStringNames.OpenExpressApp))
            {
                db.Delete(typeof(Org), db.Query().Constrain("Id").Equal(id));
            }
        }

        #endregion

        #region ITreeNode Members

        [NotUndoable, NonSerialized]
        private Org _parentOrg;
        [NotUndoable, NonSerialized]
        private IList<ITreeNode> _childrenNodes;

        object ITreeNode.Id
        {
            get { return Id; }
        }

        object ITreeNode.Pid
        {
            get { return Pid; }
        }

        public IList<ITreeNode> ChildrenNodes
        {
            get
            {
                if (null == _childrenNodes) { _childrenNodes = new List<ITreeNode>(); }
                return _childrenNodes;
            }
        }

        public ITreeNode ParentNode
        {
            get
            {
                return _parentOrg;
            }
            set
            {
                //去除以前Parent引用
                if (null != _parentOrg)
                {
                    (_parentOrg as ITreeNode).ChildrenNodes.Remove(this);
                }
                _parentOrg = value as Org;
                Pid = value == null ? default(Guid?) : _parentOrg.Id;
                if (null != value)
                {
                    if (!(value as ITreeNode).ChildrenNodes.Contains(this))
                        (value as ITreeNode).ChildrenNodes.Add(this);
                }
                OnPropertyChanged("ParentNode");
            }
        }

        #endregion

        public override string ToString()
        {
            return Name;
        }
    }
}